package com.aiwu.widget

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethod
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import android.widget.TextView
import androidx.customview.widget.ViewDragHelper
import com.aiwu.NetPlayManager
import com.aiwu.NetPlayManager.NetPlayListener
import com.aiwu.dialog.SwitchScreenLayoutDialog
import com.aiwu.library.AiwuSimulator
import com.aiwu.library.App
import com.aiwu.library.util.DisplayUtil
import com.aiwu.library.util.KeyThemeUtil
import com.aiwu.library.util.OtherSpUtil
import com.aiwu.utils.PrefsHelper
import org.citra.citra_emu.NativeLibrary
import org.citra.citra_emu.NativeLibrary.switchBottomScreen25
import org.citra.citra_emu.databinding.ViewFloatingBinding
import org.citra.citra_emu.display.ScreenLayout
import kotlin.math.max
import kotlin.math.min

/**
 * 快捷菜单栏
 */
class FloatingLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr), NetPlayListener {
    private var startCaptureTime: Long = 0
    private var viewCapturing = false
    private var isShowBottomScreen = true

    //是否上次修正聊天View的位置
    private var lastFixChatX = -1
    private val mDragHelper by lazy {
        ViewDragHelper.create(this, object : ViewDragHelper.Callback() {
            //返回true则表示可以捕获该view
            override fun tryCaptureView(view: View, i: Int): Boolean {
                return true
            }

            //对child移动的边界进行控制，
            override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int {
                val leftBound = getPaddingLeft()
                val rightBound = width - child.width - leftBound
                return min(max(left, leftBound), rightBound)
            }

            override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
                val topBound = paddingTop
                val bottomBound = height - child.height - topBound
                return min(max(top, topBound), bottomBound)
            }

            override fun onViewCaptured(capturedChild: View, activePointerId: Int) {
                viewCapturing = true
                startCaptureTime = System.currentTimeMillis()
            }

            override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
                viewCapturing = false
                val isClick = System.currentTimeMillis() - startCaptureTime < 200
                binding.run {
                    if (releasedChild === ivBottomScreen) {
                        PrefsHelper.instance.setFloatingBottomScreenLocation(
                            ivBottomScreen.x.toInt(),
                            ivBottomScreen.y.toInt()
                        )
                    } else if (releasedChild === ivScreenLayout) {
                        PrefsHelper.instance.setFloatingScreenLayoutLocation(
                            ivScreenLayout.x.toInt(),
                            ivScreenLayout.y.toInt()
                        )
                    } else if (releasedChild === chatInput) {
                        if (!isClick) {
                            PrefsHelper.instance.setFloatingChatLocation(
                                chatInput.x.toInt(),
                                chatInput.y.toInt()
                            )
                        }
                    }
                    if (isClick) {
                        //视为点击事件
                        if (releasedChild === ivBottomScreen) {
                            switchBottomScreen()
                        } else if (releasedChild === ivScreenLayout) {
                            switchScreenLayout()
                        } else if (releasedChild === chatInput) {
                            toggleChatInput()
                        }
                    }
                }
            }
        })
    }
    private val binding by lazy {
        ViewFloatingBinding.inflate(LayoutInflater.from(context), this)
    }

    init {
        init()
    }

    private fun init() {
        initView()
        visibility =
            if (OtherSpUtil.getInstance().isFloatWindowSettingWindowShow) VISIBLE else GONE
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun initView() {
        binding.chatTextInput.setOnEditorActionListener { view: TextView, action: Int, event: KeyEvent? ->
            if (action == EditorInfo.IME_ACTION_SEND) {
                val name = NetPlayManager.GetUsername()
                val msg = view.getText().toString().trim()
                if (msg.isNotEmpty()) {
                    NetPlayManager.getInstance().addNetPlayMessage("$name: $msg")
                    NativeLibrary.netPlaySendMessage25(msg)
                    view.text = ""
                }
                return@setOnEditorActionListener true
            }
            false
        }
        displayBottomScreenView()
        displayIvScreenLayout()
        displayChatLayout()
    }

    private fun switchBottomScreen() {
        isShowBottomScreen = !isShowBottomScreen
        displayBottomScreenView()
        switchBottomScreen25(isShowBottomScreen)
    }

    fun displayBottomScreenView() {
        binding.ivBottomScreen.run {
            if (PrefsHelper.instance.isQuickSwitchBottomScreen()) {
                setImageBitmap(
                    KeyThemeUtil.getControlBitmapWithKeyTheme(if (isShowBottomScreen) "bottom_screen_show" else "bottom_screen_hide")
                )
                setAlpha(AiwuSimulator.getCurrentKeyTheme().controlAlpha ?: 1.0f)
                visibility = VISIBLE
            } else {
                visibility = GONE
                setImageDrawable(null)
            }
        }
    }

    private fun displayChatLayout() {
        binding.chatInput.visibility = if (NativeLibrary.netPlayIsJoined25()) VISIBLE else GONE
    }

    private fun toggleChatInput() {
        binding.run {
            val alpha = chatInput.alpha
            val imm = context.getSystemService(
                InputMethodManager::class.java
            )
            if (alpha > 0.5f) {
                //收缩
                var x = chatInput.x.toInt()
                if (lastFixChatX != -1) {
                    x = lastFixChatX
                    lastFixChatX = -1
                }
                val y = chatInput.y.toInt()
                PrefsHelper.instance.setFloatingChatLocation(x, y)
                layoutChild(x, y, chatInput, true)
                chatTextInput.clearFocus()
                chatTextInput.visibility = GONE
                chatInput.setAlpha(0.5f)
                imm.hideSoftInputFromWindow(chatTextInput.windowToken, 0)
            } else {
                //展开
                val expandWidth = DisplayUtil.dp2px(284f)
                if (chatInput.x + expandWidth > width) {
                    lastFixChatX = chatInput.x.toInt()
                    //超出屏幕
                    val fixX = width - expandWidth
                    val y = chatInput.y.toInt()
                    PrefsHelper.instance.setFloatingChatLocation(fixX, y)
                    layoutChild(fixX, y, chatInput, true)
                } else {
                    lastFixChatX = -1
                    val x = chatInput.x.toInt()
                    val y = chatInput.y.toInt()
                    PrefsHelper.instance.setFloatingChatLocation(x, y)
                    layoutChild(x, y, chatInput, true)
                }
                chatInput.setAlpha(1.0f)
                chatTextInput.visibility = VISIBLE
                chatTextInput.requestFocus()
                imm.showSoftInput(chatTextInput, InputMethod.SHOW_FORCED)
            }
        }
    }

    /**
     * 切换屏幕布局
     */
    private fun switchScreenLayout() {
        val quickScreenLayout = PrefsHelper.instance.getQuickScreenLayout()
        if (quickScreenLayout == null) {
            switchScreenLayoutError()
            return
        }
        //正在使用的屏幕布局
        val currentScreenLayout = PrefsHelper.instance.getLastScreenConfigId()
        //如果正在使用的布局是第一个布局，那就切换到第二个布局,否则都切换到第一个布局
        useScreenLayout(if (currentScreenLayout == quickScreenLayout[0]) quickScreenLayout[1] else quickScreenLayout[0])
    }

    /**
     * 使用屏幕布局
     */
    private fun useScreenLayout(id: Int) {
        val screenConfig = PrefsHelper.instance.getScreenConfig(id)
        if (screenConfig != null && screenConfig.isCustom) {
            SwitchScreenLayoutDialog.changeToCustomScreenLayout(screenConfig, getWindowRotation())
        } else {
            if (id > ScreenLayout.MOBILE_LANDSCAPE.int) {
                //布局被删了或者怎么样
                switchScreenLayoutError()
                return
            }
            SwitchScreenLayoutDialog.changeToSystemScreenLayout(id, getWindowRotation())
        }
        PrefsHelper.instance.setLastScreenConfigId(id)
        if (DisplayUtil.isLandscape()) {
            PrefsHelper.instance.setLastLandscapeScreenConfigId(id)
        } else {
            PrefsHelper.instance.setLastPortraitScreenConfigId(id)
        }
    }

    private fun getWindowRotation(): Int {
        (context as? Activity)?.let {
            return it.windowManager.defaultDisplay.rotation
        }
        NativeLibrary.sEmulationActivity.get()?.let {
            return it.windowManager.defaultDisplay.rotation
        }
        return (App.getContext()
            .getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.rotation
    }

    /**
     * 切换屏幕布局出错
     */
    private fun switchScreenLayoutError() {
        PrefsHelper.instance.removeQuickScreenLayout()
        displayIvScreenLayout()
    }

    fun displayIvScreenLayout() {
        binding.ivScreenLayout.run {
            if (PrefsHelper.instance.isQuickScreenLayout()) {
                setImageBitmap(KeyThemeUtil.getControlBitmapWithKeyTheme("quick_screen_layout"))
                setAlpha(AiwuSimulator.getCurrentKeyTheme().controlAlpha ?: 1.0f)
                setVisibility(VISIBLE)
            } else {
                setVisibility(GONE)
                setImageDrawable(null)
            }
        }
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        restoreLocation(true)
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        restoreLocation(false)
    }

    private fun restoreLocation(requestLayout: Boolean) {
        PrefsHelper.instance.getFloatingBottomScreenLocation()?.let {
            layoutChild(it[0], it[1], binding.ivBottomScreen, requestLayout)
        }
        PrefsHelper.instance.getFloatingScreenLayoutLocation()?.let {
            layoutChild(it[0], it[1], binding.ivScreenLayout, requestLayout)
        }
        PrefsHelper.instance.getFloatingChatLocation()?.let {
            layoutChild(it[0], it[1], binding.chatInput, requestLayout)
        }
    }

    private fun layoutChild(cLeft: Int, cTop: Int, view: View, requestLayout: Boolean) {
        if (requestLayout) {
            val originalParams = view.layoutParams as LayoutParams
            val newParams = LayoutParams(originalParams.width, originalParams.height)
            newParams.setMargins(cLeft, cTop, 0, 0)
            view.setLayoutParams(newParams)
        } else {
            val cRight = cLeft + view.measuredWidth
            val cBottom = cTop + view.measuredHeight
            view.layout(cLeft, cTop, cRight, cBottom)
        }
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return mDragHelper.shouldInterceptTouchEvent(event)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (viewCapturing) {
            mDragHelper.processTouchEvent(event)
            return true
        }
        if (isCaptureViewUnder(event.x, event.y)) {
            mDragHelper.processTouchEvent(event)
            return true
        }
        return false
    }

    private fun isViewUnder(view: View?, x: Float, y: Float): Boolean {
        return if (view == null || view.visibility != VISIBLE) {
            false
        } else x >= view.left && x < view.right && y >= view.top && y < view.bottom
    }

    private fun isCaptureViewUnder(x: Float, y: Float): Boolean {
        return isViewUnder(binding.ivBottomScreen, x, y)
                || isViewUnder(binding.ivScreenLayout, x, y)
                || isViewUnder(binding.chatInput, x, y)
    }

    override fun onAddNetPlayMessage(msg: String) {
        displayChatLayout()
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        NetPlayManager.getInstance().netPlayListener = this
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        NetPlayManager.getInstance().netPlayListener = null
    }
}
